package com.example.springboot.service.impl;

import cn.hutool.core.lang.Dict;
import com.example.springboot.Exception.ServiceException;
import com.example.springboot.common.Page;
import com.example.springboot.service.StoreService;
import com.example.springboot.service.UserFavoriteProductService;
import com.example.springboot.utils.DateUtil;
import com.example.springboot.utils.MailUtil;
import com.example.springboot.utils.RandomUtil;
import com.example.springboot.utils.TokenUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 店铺表(Store)表服务实现类
 *
 * @author makejava
 * @since 2024-01-13 17:16:26
 */
@Service("storeService")
public class StoreServiceImpl implements StoreService {
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private OrdersProductMapper ordersProductMapper;
    @Autowired
    private UserFavoriteProductService userFavoriteProductService;

    @Resource
    private MailUtil mailUtil;


    /**
     * 登录
     *
     * @param account
     * @return
     */
    @Override
    public Store login(Account account) {
        // 设置登录时间
        String loginTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss");
        storeMapper.updateLoginTime(loginTime, account.getUsername());
        // 判断当前商家名是否存在
        Store storeDB = storeMapper.selectByUsernameSimple(account.getUsername());
        // 如果商家不存在，返回不存在信息
        if (storeDB == null) {
            throw new ServiceException("401", "商家不存在！");
        }
        if (storeDB.getStatus() == 0) {
            throw new ServiceException("商家已被删除，请联系管理员！");
        }
        if (storeDB.getStatus() == 2) {
            throw new ServiceException("商家已被锁定，请联系管理员！");
        }
        if (storeDB.getStatus() == 3) {
            throw new ServiceException("商家已被冻结，请联系管理员！");
        }
        if (storeDB.getStatus() == 4) {
            throw new ServiceException("商家还未通过审核！");
        }
        // 判断商家账号密码是否匹配
        if (!storeDB.getPassword().equals(account.getPassword())) {
            throw new ServiceException("商家名或密码错误！");
        }
        // 生成token回传前端
        String token = TokenUtils.genToken(storeDB.getId().toString(), storeDB.getPassword());
        storeDB.setToken(token);
        return storeDB;
    }

    /**
     * 注册
     *
     * @param account
     * @return
     */
    @Override
    public Store register(Account account) {

        // 首先，判断商家输入的账号是否存在，数据库中商家名是唯一的
        Store dbStore = storeMapper.selectByUsername(account.getUsername());
        if (dbStore != null) {
            // 商家名已存在，抛出自定义异常
            throw new ServiceException("422", "商家名已存在");
        }
        // 注册==新增商家信息
        try {
            account.setStatus(4);
            storeMapper.insert(account);
            // 返回新增的商家信息
            dbStore = storeMapper.selectByUsername(account.getUsername());
            return dbStore;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("注册失败");
        }
    }


    /**
     * 找回密码
     *
     * @param account
     */
    @Override
    public void findPassword(Account account) {
        try {
            // 首先，判断商家输入的账号是否存在，数据库中商家名是唯一的
            Store dbStore = storeMapper.selectByUsername(account.getUsername());
            if (dbStore == null) {
                // 商家名不存在，抛出自定义异常
                throw new ServiceException("423", "商家未注册！");
            }
            // 判断邮箱
            if (!dbStore.getEmail().equals(account.getEmail())) {
                // 邮箱不匹配，抛出自定义异常
                throw new ServiceException("424", "邮箱不匹配！");
            }
            // 直接随机生成密码，然后发邮件就行
            int passwordLength = 8;
            String password = RandomUtil.generateRandomPassword(passwordLength);
            System.out.println("生成的随机密码是: " + password);

            account.setPassword(DigestUtils.md5Hex(password));

            // 发送邮件
            MailUtil mailUtil = new MailUtil();
            String recipient = account.getEmail();
            Mail mail = new Mail();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            mail.setRecipient(recipient);
            mail.setSubject("并州电子数码商城 \n 密码重置通知 \n" + sdf + "\n");
            mail.setContent("亲爱的用户：您好！\n" +
                    "\n" + "    您收到这封电子邮件是因为您 (也可能是某人冒充您的名义) 申请了修改账号密码。假如这不是您本人所申请, 请不用理会这封电子邮件, 但是如果您持续收到这类的信件骚扰, 请您尽快联络管理员。\n" +
                    "\n" +
                    "   您的密码已重置，新密码为： \n" + "\n  " +
                    password + "\n\n"
            );
            mailUtil.sendSimpleMail(mail);

            // 修改密码
            storeMapper.updatePassword(account);
        } catch (ServiceException e) {
            throw new ServiceException("修改密码失败");
        }
    }

    /**
     * 获取所有商家信息
     *
     * @return
     */
    @Override
    public List<Store> selectAll() {
        return storeMapper.selectAll();
    }

    /**
     * 根据ID删除
     *
     * @param id
     */
    @Override
    public void deleteById(Integer id) {
        try {
            storeMapper.deleteById(id);
        } catch (Exception e) {
            throw new ServiceException("删除失败");
        }
    }


    /**
     * 根据ID更新信息
     *
     * @param store
     */
    @Override
    public void updateById(Store store) {
        try {
            storeMapper.updateById(store);
        } catch (Exception e) {
            throw new ServiceException("更新失败");
        }
    }

    /**
     * 条件查询
     *
     * @param username
     * @param name
     * @param phone
     * @param status
     * @return
     */
    @Override
    public List<Store> selectByManyCondition(String username, String name, String phone, Integer status) {
        try {
            return storeMapper.selectByManyCondition(username, name, phone, status);
        } catch (Exception e) {
            throw new ServiceException("查询失败");
        }
    }

    /**
     * 分页查询
     *
     * @param currentPage
     * @param pageSize
     * @return
     */
    @Override
    public Page<Store> selectByPage(Integer currentPage, Integer pageSize) {
        try {
            // 计算起始行
            Integer startRow = (currentPage - 1) * pageSize;

            // 查询总记录数
            int totalCount = storeMapper.selectAll().size();
            // 查询分页数据
            List<Store> users = storeMapper.selectByPage(startRow, pageSize);

            // 封装返回结果
            Page<Store> page = new Page<>();
            page.setList(users);
            page.setTotal(totalCount);
            return page;
        } catch (ServiceException e) {
            throw new ServiceException("分页查询失败！");
        }

    }

//    /**
//     * 分页查询 条件查询
//     * @param currentPage
//     * @param pageSize
//     * @param username
//     * @param name
//     * @param phone
//     * @param email
//     * @return
//     */
//    @Override
//    public Page<Store> selectByManyConditionInpage(Integer currentPage, Integer pageSize, String username, String name, String phone, String email) {
//        // 计算起始行
//        Integer startRow = (currentPage - 1) * pageSize;
//
//        // 查询总记录数
//        int totalCount = storeMapper.selectByManyCondition(username,name,phone,email).size();
//        // 查询分页数据
//        List<Store> users = storeMapper.selectByManyConditionInpage(startRow, pageSize,username,name,phone,email);
//
//        // 封装返回结果
//        Page<Store> page = new Page<>();
//        page.setList(users);
//        page.setTotal(totalCount);
//        return page;
//    }


    /**
     * 分页查询 条件查询
     *
     * @param currentPage
     * @param pageSize
     * @param username
     * @param name
     * @param phone
     * @param status
     * @return
     */
    @Override
    public Page<Store> selectByManyConditionInpage(Integer currentPage, Integer pageSize, String username, String name, String phone, Integer status) {
        try {
            // 计算起始行
            Integer startRow = (currentPage - 1) * pageSize;

            // 查询总记录数
            int totalCount = storeMapper.selectByManyCondition(username, name, phone, status).size();
            // 查询分页数据
            List<Store> users = storeMapper.selectByManyConditionInpage(startRow, pageSize, username, name, phone, status);

            // 封装返回结果
            Page<Store> page = new Page<>();
            page.setList(users);
            page.setTotal(totalCount);
            return page;
        } catch (ServiceException e) {
            throw new ServiceException("条件查询失败！");
        }

    }

    /**
     * 分页查询 条件查询
     *
     * @param currentPage
     * @param pageSize
     * @param username
     * @param name
     * @param phone
     * @return
     */
    @Override
    public Page<Store> selectByManyConditionNoStatusInpage(Integer currentPage, Integer pageSize, String username, String name, String phone) {
        try {
            // 计算起始行
            Integer startRow = (currentPage - 1) * pageSize;

            // 查询总记录数
            int totalCount = storeMapper.selectByManyConditionNoStatus(username, name, phone).size();
            // 查询分页数据
            List<Store> users = storeMapper.selectByManyConditionNoStatusInpage(startRow, pageSize, username, name, phone);

            // 封装返回结果
            Page<Store> page = new Page<>();
            page.setList(users);
            page.setTotal(totalCount);
            return page;
        } catch (ServiceException e) {
            throw new ServiceException("条件查询失败！");
        }

    }

    /**
     * 批量删除
     *
     * @param ids
     */
    @Override
    public void deleteByIds(List<Integer> ids) {
        try {
            for (Integer id : ids) {
                storeMapper.deleteById(id);
            }
        } catch (Exception e) {
            throw new ServiceException("删除失败");
        }
    }

    /**
     * 添加商户
     *
     * @param store
     */
    @Override
    public void addStore(Store store) {
        Store storeDB = null;
        try {
            // 先查询账号是否存在
            storeDB = storeMapper.selectByUsername(store.getUsername());
        } catch (ServiceException e) {
            throw new ServiceException("查询账号失败！");
        }


        if (storeDB == null) {
            try {
                //  账号不存在，添加
                storeMapper.addStore(store);
            } catch (ServiceException e) {
                throw new ServiceException("添加失败");
            }
        } else {
            //  账号存在，抛出异常
            throw new ServiceException("账号已存在");
        }
    }

    /**
     * 根据id查询商家
     *
     * @param id
     * @return
     */
    @Override
    public Store selectSimpleById(Integer id) {
        try {
            return storeMapper.selectSimpleById(id);
        } catch (Exception e) {
            throw new ServiceException("商家不存在");
        }
    }

    /**
     * 加载所有的商家
     *
     * @return
     */
    @Override
    public List<Store> loadAllStore() {
        try {
            return storeMapper.loadAllStore();
        } catch (Exception e) {
            throw new ServiceException("加载商家失败");
        }
    }

    @Override
    public long getTotal() {
        try {
            return storeMapper.getTotal();
        } catch (Exception e) {
            throw new ServiceException("获取商家总数失败");
        }
    }

    @Override
    public List<Store> storeTop10() {
        try {
            List<Store> stores = storeMapper.selectAll();
            for (Store store : stores) {
                // 对店铺内的商品的销量进行累加
                List<Product> products = store.getProducts();
                BigDecimal sales = products.stream()
                        .map(Product::getSales)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                store.setSales(sales);

                // 对店铺内的商品的销量进行累加
                BigDecimal totalSales = BigDecimal.ZERO;
                BigDecimal transaction = BigDecimal.ZERO;
                BigDecimal totalTransactions = BigDecimal.ZERO;

                for (Product product : products) {
                    totalSales = totalSales.add(product.getSales());
                    transaction = product.getPrice().multiply(product.getSales());
                    totalTransactions = totalTransactions.add(transaction);
                }
                store.setTransactions(totalTransactions);
            }
            // 对sotres集合的销量进行排序筛选出交易额前十的商家
            stores.sort(Comparator.comparing(Store::getTransactions).reversed());
            return stores.subList(0, 10);
        } catch (Exception e) {
            throw new ServiceException("获取商家排行榜失败");
        }
    }

    @Override
    public BigDecimal[] getTodayInfo(Integer id) {
        try {

            // 今日时间段
//            String startTime = DateUtil.getStartOfDayFormatted();
//            String endTime = DateUtil.getEndOfDayFormatted();

            Date startTime = DateUtil.getStartOfToday();
            Date endTime = DateUtil.getEndOfToday();

            Store store = storeMapper.selectById(id);
            BigDecimal[] res = new BigDecimal[4];

            // 获取该商家今日的订单数量

            Integer storeId = id;
            List<OrdersProduct> ordersProducts = ordersProductMapper.selectByStoreId(storeId);
            List<Integer> ordersIds = ordersProducts.stream().map(OrdersProduct::getOrdersId).distinct().collect(Collectors.toList());
            if (ordersIds.size() > 0) {
                int orderCount = ordersMapper.selectCountInOrdersIdsAndTime(ordersIds, startTime, endTime);
                res[0] = new BigDecimal(orderCount);
            } else {
                res[0] = new BigDecimal(0);
            }

            // 获取该商家今日的商品上架数量.
            int productCount = productMapper.selectCountByStoreIdAndTime(id, startTime, endTime);
            res[1] = new BigDecimal(productCount);

            // 对店铺内的商品的销量进行累加
            List<Product> products = store.getProducts();
            BigDecimal totalSales = BigDecimal.ZERO;
            BigDecimal transaction = BigDecimal.ZERO;
            BigDecimal totalTransactions = BigDecimal.ZERO;

            for (Product product : products) {
                totalSales = totalSales.add(product.getSales());
                transaction = product.getPrice().multiply(product.getSales());
                totalTransactions = totalTransactions.add(transaction);
            }
            res[2] = totalSales;
            res[3] = totalTransactions;

            return res;

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("获取商家今日信息失败");
        }
    }

    @Override
    public List<Dict> productCharts(Integer id) {
        // 尝试获取订单服务
        try {
            // 获取TOP20的商品集合
            List<Product> list = productMapper.selectTop10CategoryStore(id);

            // 创建折线列表
            List<Dict> lineList = new ArrayList<>();

            // 在UserFavoriteProductService获取这个商品的收藏量
            for (Product product : list) {
                product.setFavoriteCount(userFavoriteProductService.getFavoriteCount(product.getId()));
                // 创建字典
                Dict dict = Dict.create();
                // 将日期和金额总和放入字典
                Dict line = dict.set("productName", product.getName())
                        .set("sales", product.getSales())
                        .set("views", product.getViews())
                        .set("favoriteCount", product.getFavoriteCount());
                // 将字典添加到折线列表
                lineList.add(line);
            }
            // 返回折线统计图数据
            return lineList;
        } catch (Exception e) {
            throw new RuntimeException("请求折线统计图数据失败");
        }
    }

    @Override
    public Store selectById(Integer id) {
        try {
            return storeMapper.selectById(id);
        } catch (Exception e) {
            throw new ServiceException("请求店铺信息失败");
        }
    }

    @Override
    public void changePassword(Account account) {
        // 首先，判断用户输入的账号是否存在，数据库中用户名是唯一的
        Store dbStore = storeMapper.selectById(account.getId());
        if (dbStore == null) {
            // 用户名不存在，抛出自定义异常
            throw new ServiceException("404", "管理员未注册！");
        }
        // 判断用户输入的旧密码是否正确
        if (!dbStore.getPassword().equals(account.getPassword())) {
            // 旧密码不正确，抛出自定义异常
            throw new ServiceException("488", "旧密码不正确！");
        }
        // 修改密码
        dbStore.setPassword(account.getNewPassword());
        // 更新数据库中的管理员信息
        try {
            int row = storeMapper.changePassword(dbStore);
            if (row > 0) {
                // 修改成功
                // 让之前的账号token过期
                // 生成新的token
                String token = TokenUtils.genToken(dbStore.getId().toString(), dbStore.getPassword());
                dbStore.setToken(token);
            }
        } catch (ServiceException e) {
            throw new ServiceException("488", "修改密码失败!");
        }
    }

}
